<?php
namespace Dao;
/**
 * Class Db
 *
 * @package Dao
 * @description rds数据库服务基类
 */
class Db extends \Base\Dao\Db {

	const DB_NAME       = 'edu';  //库名, 与项目名称一致
	const TABLE_PREFIX  = '';  //表前缀, 与项目名称一致

    protected $json_fields;

    /**
     * 选择库实例
     *
     * @param string $name 库名, 默认与项目名称一致
     *
     * @return \S\Db\Mysql MySQL实例
     */
    public static function db($name=self::DB_NAME) {
        return self::getInstance($name);
    }

    /**
     * 选择表
     * 为避免可能与其他无关项目的表混淆, 所有表名应带有项目名称的表前缀, 获取表名必须使用此方法
     *
     * @param string $table 表名
     *
     * @return string 带有项目名称作为前缀的表名, 格式: {APP_NAME}_table
     */
    public static function table($table) {
		return self::TABLE_PREFIX.$table;
    }

    /**
     * dataTable方法
     * @param array $params
     * @param array $cols
     * @param array orders
     * @return array
     */
    public function dataTable($params, array $cols = array(), array $orders = array('ctime'=>'desc')) {
        $table = static::table(static::TABLE_NAME);
        $table_params = \S\Util\DataTable::dealTable();
        $limit = 0;
        $count = 0;

        $is_count = false;
        if ($table_params) {
            $params = array_merge($params, $table_params['search']);
            $orders  = array_merge($orders, $table_params['order']);
            $limit = $table_params['limit'];
            $is_count = true;
        }

        $params = self::encrypt($params);
        if ($is_count) {
            $count  = self::db()->count($table, $params);
        }
        $data = self::db()->query($table, $params, $cols, $orders, $limit) ?: [];
        $ret['data'] = static::decode($data); //做decode操作
        $ret['draw']                 = $table_params['draw'];
        $ret['iTotalRecords']        = $count;
        $ret['iTotalDisplayRecords'] = $count;
        return $ret;
    }

    /**
     * 根据sql语句分页查询(使用dataTable组件)
     *
     * @param string $sql sql语句
     * @param array $params 查询条件, k-v结构array
     *                      e.g.
     *                      array(
     *                          'col_i' => 'value',
     *                          'col_ii' => 1,
     *                      )
     * @param int   $style default 2 结果读取形式, 默认键值为表字段
     *
     * @return array 分页查询结果
     */
    public static function dataTableSql($sql, $params = array(), $style = \PDO::FETCH_ASSOC) {
        $sql          = trim($sql, ';');
        $table_params = \S\Util\DataTable::dealTable();
        if ($table_params) {
            $params = array_merge($params, $table_params['search']);
            $sql    = preg_replace('/^\s*SELECT\s+/i', 'SELECT SQL_CALC_FOUND_ROWS ', $sql);

            // 直接将 limit 加到sql的最后，理论上这里是读操作，不会出问题
            $limit = $table_params['limit'];
            if ($limit) {
                $sql .= ' LIMIT ' . intval(array_shift($limit)) . ", " . intval(array_shift($limit));
            }

            $ret['data']                 = self::db()->qsql($sql, $params, $style);
            $ret['draw']                 = $table_params['draw'];
            $ret['iTotalRecords']        = self::db()->execute('SELECT FOUND_ROWS()')->fetchColumn();
            $ret['iTotalDisplayRecords'] = $ret['iTotalRecords'];
        } else {
            $ret['data'] = self::db()->qsql($sql, $params, $style);
        }

        return $ret;
    }

    //decode操作,支持多维数组
    protected static function decode(array $data) {
        if (!$data) {
            return [];
        }

        $easy_arr = false;
        foreach($data as &$val) {
            if (is_array($val)) {
                $val = static::decode($val);
            } else {
                $easy_arr = true;
                break;
            }
        }

        if ($easy_arr) {
            foreach(static::$json_keys as $key) {
                if (isset($data[$key])) {
                    $data[$key] = json_decode($data[$key], true) ?: [];
                } else {
                    $data[$key] = [];
                }
            }
            $data = static::decrypt($data);
        }

        return $data;
    }

    //encode操作
    protected static function encode(array $data) {
        if (!$data) {
            return [];
        }
        $data = static::encrypt($data);

        foreach(static::$json_keys as $key) {
            if (isset($data[$key])) {
                $data[$key] = json_encode(isset($data[$key]) ? : new \stdClass());
            }
        }

        return $data;
    }


}
